--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
meshchatx/src/backend/integrity_manager.py 9d8611bb97df55bcb1fb38bc6de17e9f7846ffa2 (9d8611bb) Text, 4.78 KB
Tff7b72import T7ee787os
Tff7b72import T7ee787hashlib
Tff7b72import T7ee787json
Tff7b72from T7ee787pathlib Tff7b72import Te6edf3Path
Tff7b72from T7ee787datetime Tff7b72import Te6edf3UTCTb4b4b4, Te6edf3datetime
Tff7b72class T56d364IntegrityManagerTb4b4b4:
T8b949e"""Manages the integrity of the database and identity files at rest."""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3storage_dirTb4b4b4, Te6edf3database_pathTb4b4b4, Te6edf3identity_hashTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3PathTb4b4b4(Te6edf3storage_dirTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdatabase_path Tff7b72= Te6edf3PathTb4b4b4(Te6edf3database_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffidentity_hash Tff7b72= Te6edf3identity_hash
Tff7b72selfTff7b72.Td2a8ffmanifest_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72/ Ta5d6ff"Ta5d6ffintegrity-manifest.jsonTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffissues Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72def Td2a8ff_hash_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3sha256_hash Tff7b72= Te6edf3hashlibTff7b72.Td2a8ffsha256Tb4b4b4(Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3file_pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72for Te6edf3byte_block Tff7b72in Tffa657iterTb4b4b4(Tff7b72lambdaTb4b4b4: Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(T79c0ff4096Tb4b4b4)Tb4b4b4, Ta5d6ffbTa5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3sha256_hashTff7b72.Td2a8ffupdateTb4b4b4(Te6edf3byte_blockTb4b4b4)
Tff7b72return Te6edf3sha256_hashTff7b72.Td2a8ffhexdigestTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffcheck_integrityTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Verify the current state against the last saved manifest."""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffmanifest_pathTff7b72.Td2a8ffexistsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72TrueTb4b4b4, Tb4b4b4[Ta5d6ff"Ta5d6ffInitial run - no manifest yetTa5d6ff"Tb4b4b4]
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmanifest_pathTb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3manifest Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadTb4b4b4(Te6edf3fTb4b4b4)
Te6edf3issues Tff7b72= Tb4b4b4[Tb4b4b4]
T8b949e# Check Database
Te6edf3db_rel Tff7b72= Tffa657strTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdatabase_pathTff7b72.Td2a8ffrelative_toTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4)
Te6edf3actual_db_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ff_hash_fileTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdatabase_pathTb4b4b4)
Tff7b72if Te6edf3actual_db_hash Tff7b72and Te6edf3actual_db_hash Tff7b72!= Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4, Tb4b4b4{Tb4b4b4}Tb4b4b4)Tff7b72.Td2a8ffgetTb4b4b4(
Te6edf3db_rel
Tb4b4b4)Tb4b4b4:
Te6edf3issuesTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDatabase modified: Tffd700{Te6edf3db_relTffd700}Ta5d6ff"Tb4b4b4)
T8b949e# Check Identities and other critical files in storage_dir
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files_in_dir Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3files_in_dirTb4b4b4:
Te6edf3full_path Tff7b72= Te6edf3PathTb4b4b4(Te6edf3rootTb4b4b4) Tff7b72/ Te6edf3file
T8b949e# Skip the manifest itself and temporary sqlite files
Tff7b72if Tb4b4b4(
Te6edf3file Tff7b72== Ta5d6ff"Ta5d6ffintegrity-manifest.jsonTa5d6ff"
Tff7b72or Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff-walTa5d6ff"Tb4b4b4)
Tff7b72or Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff-shmTa5d6ff"Tb4b4b4)
Tb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3rel_path Tff7b72= Tffa657strTb4b4b4(Te6edf3full_pathTff7b72.Td2a8ffrelative_toTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4)
Te6edf3actual_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ff_hash_fileTb4b4b4(Te6edf3full_pathTb4b4b4)
Tff7b72if Te6edf3rel_path Tff7b72in Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4, Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3actual_hash Tff7b72!= Te6edf3manifestTb4b4b4[Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4]Tb4b4b4[Te6edf3rel_pathTb4b4b4]Tb4b4b4:
Te6edf3issuesTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFile modified: Tffd700{Te6edf3rel_pathTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# New files are also a concern for integrity
Te6edf3issuesTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffNew file detected: Tffd700{Te6edf3rel_pathTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3issuesTb4b4b4:
Te6edf3m_date Tff7b72= Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdateTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffUnknownTa5d6ff"Tb4b4b4)
Te6edf3m_time Tff7b72= Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftimeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffUnknownTa5d6ff"Tb4b4b4)
Te6edf3m_id Tff7b72= Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffUnknownTa5d6ff"Tb4b4b4)
Te6edf3issuesTff7b72.Td2a8ffinsertTb4b4b4(
T79c0ff0Tb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffLast integrity snapshot: Tffd700{Te6edf3m_dateTffd700}Ta5d6ff Tffd700{Te6edf3m_timeTffd700}Ta5d6ff (Identity: Tffd700{Te6edf3m_idTffd700}Ta5d6ff)Ta5d6ff"
Tb4b4b4)
T8b949e# Check if identity matches
Tff7b72if Tb4b4b4(
Tff7b72selfTff7b72.Td2a8ffidentity_hash
Tff7b72and Te6edf3m_id Tff7b72!= Ta5d6ff"Ta5d6ffUnknownTa5d6ff"
Tff7b72and Tff7b72selfTff7b72.Td2a8ffidentity_hash Tff7b72!= Te6edf3m_id
Tb4b4b4)Tb4b4b4:
Te6edf3issuesTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffIdentity mismatch! Manifest belongs to: Tffd700{Te6edf3m_idTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffissues Tff7b72= Te6edf3issues
Tff7b72return Tffa657lenTb4b4b4(Te6edf3issuesTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4, Te6edf3issues
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72return Tff7b72FalseTb4b4b4, Tb4b4b4[Ta5d6fffTa5d6ff"Ta5d6ffIntegrity check failed: Tffd700{Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4]
Tff7b72def Td2a8ffsave_manifestTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Snapshot the current state of critical files."""
Tff7b72tryTb4b4b4:
Te6edf3files Tff7b72= Tb4b4b4{Tb4b4b4}
T8b949e# Hash all critical files in storage_dir recursively
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files_in_dir Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3files_in_dirTb4b4b4:
Te6edf3full_path Tff7b72= Te6edf3PathTb4b4b4(Te6edf3rootTb4b4b4) Tff7b72/ Te6edf3file
T8b949e# Skip the manifest itself and temporary sqlite files
Tff7b72if Tb4b4b4(
Te6edf3file Tff7b72== Ta5d6ff"Ta5d6ffintegrity-manifest.jsonTa5d6ff"
Tff7b72or Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff-walTa5d6ff"Tb4b4b4)
Tff7b72or Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff-shmTa5d6ff"Tb4b4b4)
Tb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3rel_path Tff7b72= Tffa657strTb4b4b4(Te6edf3full_pathTff7b72.Td2a8ffrelative_toTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4)
Te6edf3filesTb4b4b4[Te6edf3rel_pathTb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ff_hash_fileTb4b4b4(Te6edf3full_pathTb4b4b4)
Te6edf3now Tff7b72= Te6edf3datetimeTff7b72.Td2a8ffnowTb4b4b4(Te6edf3UTCTb4b4b4)
Te6edf3manifest Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4: T79c0ff1Tb4b4b4,
Ta5d6ff"Ta5d6fftimestampTa5d6ff"Tb4b4b4: Te6edf3nowTff7b72.Td2a8fftimestampTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffdateTa5d6ff"Tb4b4b4: Te6edf3nowTff7b72.Td2a8ffstrftimeTb4b4b4(Ta5d6ff"Ta5d6ff%Ta5d6ffY-Ta5d6ff%Ta5d6ffm-Tffd700%dTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fftimeTa5d6ff"Tb4b4b4: Te6edf3nowTff7b72.Td2a8ffstrftimeTb4b4b4(Ta5d6ff"Ta5d6ff%Ta5d6ffH:Ta5d6ff%Ta5d6ffM:Ta5d6ff%Ta5d6ffSTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffidentity_hashTb4b4b4,
Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4: Te6edf3filesTb4b4b4,
Tb4b4b4}
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmanifest_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3jsonTff7b72.Td2a8ffdumpTb4b4b4(Te6edf3manifestTb4b4b4, Te6edf3fTb4b4b4, Te6edf3indentTff7b72=T79c0ff2Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to save integrity manifest: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72False
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────